package com.baoyz.widget;

import java.security.InvalidParameterException;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;

/**
 * Created by baoyz on 14/10/31.
 */
class WaterDropDrawable extends RefreshDrawable implements Runnable {

	private static final float MAX_LEVEL = 10000;
	private static final float CIRCLE_COUNT = ProgressStates.values().length;
	private static final float MAX_LEVEL_PER_CIRCLE = MAX_LEVEL / CIRCLE_COUNT;

	private int mLevel;
	private Point p1, p2, p3, p4;
	private Paint mPaint;
	private Path mPath;
	private int mHeight;
	private int mWidth;
	private int mTop;
	private int[] mColorSchemeColors;
	@SuppressWarnings("unused")
	private ProgressStates mCurrentState;
	private Handler mHandler = new Handler();
	private boolean isRunning;

	private enum ProgressStates {
		ONE, TWO, TREE, FOUR
	}

	public WaterDropDrawable(Context context, PullRefreshLayout layout) {
		super(context, layout);
		mPaint = new Paint();
		mPaint.setColor(Color.BLUE);
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setAntiAlias(true);
		mPath = new Path();
		p1 = new Point();
		p2 = new Point();
		p3 = new Point();
		p4 = new Point();
	}

	@Override
	public void draw(Canvas canvas) {

		canvas.save();
		canvas.translate(0, mTop > 0 ? mTop : 0);

		mPath.reset();
		mPath.moveTo(p1.x, p1.y);
		mPath.cubicTo(p3.x, p3.y, p4.x, p4.y, p2.x, p2.y);
		canvas.drawPath(mPath, mPaint);

		canvas.restore();
	}

	@Override
	protected void onBoundsChange(Rect bounds) {
		mWidth = bounds.width();
		updateBounds();
		super.onBoundsChange(bounds);
	}

	private void updateBounds() {

		int height = mHeight;
		int width = mWidth;

		if (height > getRefreshLayout().getFinalOffset()) {
			height = getRefreshLayout().getFinalOffset();
		}

		final float percent = height
				/ (float) getRefreshLayout().getFinalOffset();
		int offsetX = (int) (width / 2 * percent);
		int offsetY = 0;
		p1.set(offsetX, offsetY);
		p2.set(width - offsetX, offsetY);
		p3.set(width / 2 - height, height);
		p4.set(width / 2 + height, height);
	}

	@Override
	public void setColorSchemeColors(int[] colorSchemeColors) {
		if (colorSchemeColors == null || colorSchemeColors.length < 4)
			throw new InvalidParameterException(
					"The color scheme length must be 4");
		mPaint.setColor(colorSchemeColors[0]);
		mColorSchemeColors = colorSchemeColors;
	}

	@Override
	public void setPercent(float percent) {
		mPaint.setColor(evaluate(percent, mColorSchemeColors[0],
				mColorSchemeColors[1]));
	}

	private void updateLevel(int level) {
		int animationLevel = level == MAX_LEVEL ? 0 : level;

		int stateForLevel = (int) (animationLevel / MAX_LEVEL_PER_CIRCLE);
		mCurrentState = ProgressStates.values()[stateForLevel];

		float percent = level % 2500 / 2500f;
		int startColor = mColorSchemeColors[stateForLevel];
		int endColor = mColorSchemeColors[(stateForLevel + 1)
				% ProgressStates.values().length];
		mPaint.setColor(evaluate(percent, startColor, endColor));
	}

	@Override
	public void offsetTopAndBottom(int offset) {
		mHeight += offset;
		mTop = mHeight - getRefreshLayout().getFinalOffset();
		updateBounds();
		invalidateSelf();
	}

	@Override
	public void start() {
		mLevel = 2500;
		isRunning = true;
		mHandler.postDelayed(this, 20);
	}

	@Override
	public void stop() {
		mHandler.removeCallbacks(this);
	}

	@Override
	public boolean isRunning() {
		return isRunning;
	}

	@Override
	public void run() {
		mLevel += 60;
		if (mLevel > MAX_LEVEL)
			mLevel = 0;
		if (isRunning) {
			mHandler.postDelayed(this, 20);
			updateLevel(mLevel);
			invalidateSelf();
		}
	}

	private int evaluate(float fraction, int startValue, int endValue) {
		int startInt = startValue;
		int startA = (startInt >> 24) & 0xff;
		int startR = (startInt >> 16) & 0xff;
		int startG = (startInt >> 8) & 0xff;
		int startB = startInt & 0xff;

		int endInt = endValue;
		int endA = (endInt >> 24) & 0xff;
		int endR = (endInt >> 16) & 0xff;
		int endG = (endInt >> 8) & 0xff;
		int endB = endInt & 0xff;

		return ((startA + (int) (fraction * (endA - startA))) << 24)
				| ((startR + (int) (fraction * (endR - startR))) << 16)
				| ((startG + (int) (fraction * (endG - startG))) << 8)
				| ((startB + (int) (fraction * (endB - startB))));
	}

}